home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
hardware
/
gm1507
/
g_mouse.asm
< prev
next >
Wrap
Assembly Source File
|
1994-10-27
|
26KB
|
1,222 lines
; -----------------------------------------------------------------------------
; G_MOUSE.ASM Graphical mouse pointer in 80x25 text modes on EGA/VGA.
; For Pascal and C/C++, real mode only.
;
; g_Mouse Interface Version 1.42
;
; Copyright(c) 1993,94 by B-coolWare.
; Written by Bobby Z.
; Portions written by D. Dokolin.
; -----------------------------------------------------------------------------
; "Nice, nice. Not excellent, but nice..."
;
; (Mel Brooks)
;
; License.
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;SOFTWARE STATUS:
;
;This software is copyrighted free one. This means that it is distributed
; free of charge and that you must keep copyright notice with it. Usually this
; also means that you cannot modify the code, but it is not the case with
; this one (see grant of license for details). Note that it is not public
; domain software, that is author reserves copyright for it as well as some
; other rights.
;
;GRANT OF LICENSE:
;
;You are hereby granted the right to use this software in either commercial
; or non-commercial products provided that you do not charge any extra fee
; for this code and that you keep copyright notice unchanged.
;You are also granted the right to distribute this code freely in its original
; unmodified form provided that you do not charge any fee that exceed your
; expences from doing it.
;You also may modify the code to add new features or eliminate bugs or
; incompatibilites you discovered and distribute modified code provided that
; you add a notice that the code was modified. If you do any modifications
; to the code, please send me modified version so that I'll be able to
; reflect changes in the next releases. Regardless of the extent of modifica-
; tions the code should remain free and will still copyright(c) by B-coolWare.
;If you break any of the rules mentioned you'll be liable for violation of
; Russian Copyright Law in Computer Programs and Databases as well as other
; national or international laws and treaties. The parties that acquired this
; code from you will still have their rights as long as they comply with this
; license.
;
;DISCLAIMER:
;
;Author disclaims all warranties, whether express or implied, of code quality,
; reliability or fitness for a particular purpose. I can only guarantee that it
; will occupy disk space. Though this code was thoroughly tested, the possibi-
; lity of errors can't be eliminated. Do not blame me if something goes wrong -
; you were warned.
;
;AUTHOR'S LIABILITY:
;
;In case of taking damage due to use, misuse or inability to use, this code,
; whether it is physical damage to your hardware, loss of data or profits,
; or any similar damages author shall not be liable for it. The whole risk is
; with you.
;
;AUTHOR'S EXCLUSIVE RIGHTS:
;
;Author reserves the right to use this code in any commercial or non-
; commercial software of his own design, the right to change the code partially
; or in whole without notification to its users and the right to change its
; status (to shareware, for example).
;
;How to contact author:
;~~~~~~~~~~~~~~~~~~~~~~
;If you experiencing problems with this code or have any suggestions, bug
; fixes or just wanna chat, refer to the following addresses:
;
; e-mail (preferrable):
;
; 2:5028/52.6 (FIDOnet)
; bob@ymz.yaroslavl.su (internet)
;
; paper mail:
;
; 150031,
; 10/4/13 Dobrynina Str.,
; Yaroslavl,
; Russia
;
; Vladimir M. Zakharychev (aka Bobby Z.)
;
; Letters both in Russian and in English are welcome. Please do not use any
; other language if you want to be answered. Letter bombs are always
; returned to sender... shhhh-boom-BANG! :)
;
; Thank you for your interest in B-coolWare products.
;
;------------------------------------------------------------------------------
; Note for TV users:
; You MUST CORRECT Views.WriteView's logic in part determining if mouse is
; inside the area that will be drawn over, because now mouse pointer will
; occupy 4 characters instead of 1 when using ordinary mouse pointer. You also
; should change ShowMouse and HideMouse methods to call gShowMouse and
; gHideMouse when graphical pointer is in use. You can do it by allocating a
; boolean flag that indicates which pointer is used and proceed accordingly.
; The other way is to call Intercept33 at program startup, which will catch
; some mouse driver's functions to operate properly with graphical pointer, and
; call Untercept33 before program stop.
; -----------------------------------------------------------------------------
;
; History:
; 25 Oct 1993 initial release
; 21 Jan 1994 added some improvements
; 08 Feb 1994 adopted for Turbo Vision (Real mode only)
; 14 Apr 1994 slightly optimized and commented
; 22 Aug 1994 some corrections made
; 25 Oct 1994 some more corrections made
; This code needs Turbo Assembler 2.5 or above to be compiled.
MODEL TPASCAL ; uncomment this to use with TP/BP
; MODEL LARGE,C ; uncomment this to use with C/C++ compilers
; ^^^^^ change to preferred memory model
.CODE
LOCALS ; allow local symbols started with @@
JUMPS ; smart jumps - no "jump out of range" errors
; two special defines control the way this code is assembled:
;
; __use_286__ forces 286-specific instructions to be compiled in certain
; places
; __use_386__ forces 386-specific instructions to be compiled in certain
; places
;
ifdef __use_386__
ifndef __use_286__
__use_286__ equ 1
endif
.386
endif
ifdef __use_286__
ifndef __use_386__
.286
endif
endif
_bp EQU <BYTE PTR>
_wp EQU <WORD PTR>
load MACRO reg, Reference
mov reg,offset Reference
ENDM
ldx MACRO Reference
load dx,Reference
ENDM
lsi MACRO Reference
load si,Reference
ENDM
ldi MACRO Reference
load di,Reference
ENDM
callf MACRO Address
call dword ptr Address
ENDM
clr MACRO reg
sub reg,reg
ENDM
C1Code EQU 0DEh ; '▐'
C2Code EQU 0DDh ; '▌'
C3Code EQU 0D7h ; '╫'
C4Code EQU 0D8h ; '╪'
PUBLIC gInitMouse, gShowMouse, gHideMouse, gMouseGotoXY, gDoneMouse
PUBLIC gMouseWhereX, gMouseWhereY, gMouseActive
PUBLIC Intercept33, Untercept33
PUBLIC gMouseSetChars, gMouseGetChars
; PUBLICs list by name and function as to appear in interface section:
;
; INIT/DEINIT FUNCTIONS
;
; procedure gInitMouse( doModeFlip : Boolean ); far;
; - initializes g_Mouse. doModeFlip controls whether we should program VGA for
; 8x16 character matrix size (allows smooth cursor movement).
;
; procedure gDoneMouse( doModeFlip : Boolean ); far;
; - deinitialize g_Mouse. Should be called prior to program exit if gInitMouse
; was called. doModeFlip controls whether the effect of gInitMouse with
; doModeFlip of TRUE should be undone.
;
; procedure gMouseSetChars( C1, C2, C3, C4 : Char ); far;
; - sets four characters that will be used to substitute mouse pointer on
; screen.
;
; procedure gMouseGetChars( var C1, C2, C3, C4 : Char ); far;
; - returns current substitution character codes.
;
; LOW-LEVEL INTERFACE FUNCTIONS
;
; procedure gShowMouse; far;
; - analogue to ShowMouse. Displays mouse pointer on screen.
;
; procedure gHideMouse; far;
; - analogue to HideMouse. Hides mouse pointer off screen.
;
; procedure gMouseGotoXY( X, Y : Integer ); far;
; - sets new mouse pointer position.
;
; function gMouseWhereX : Integer;
; - returns current mouse X position (in terms of characters, not pixels).
;
; function gMouseWhereY : Integer;
; - returns current mouse Y position (in terms of characters, not pixels).
;
; function gMouseActive : Boolean;
; - returns TRUE if g_Mouse event handler is active.
;
; HIGH-LEVEL INTERFACE FUNCTIONS
;
; procedure Intercept33; far;
; - provides high-level interface to g_Mouse intercepting Mouse Services
; Interrupt (INT 33h) eliminating need to call any of low-level interface
; functions.
;
; procedure Untercept33; far;
; - undoes the effect of Intercept33.
;
; when using In(Un)tercept33 functions all mouse services works fine. Although
; if you do not use them, you may not use any of mouse services directly for
; it will crush g_Mouse system leading to unpredictable results. You may use
; only functions listed in low-level interface section to communicate with
; mouse if In(Un)tercept33 functions are not used. I suggest that you will use
; In(Un)tercept33 for your own convenience. Just call Intercept33 right on
; program startup just AFTER calling gInitMouse and call Untercept33 before
; program exit just before calling gDoneMouse. Intercept33 will not grab INT
; 33h vector if g_Mouse was not initialized due to any reason, whether you
; forgot to call gInitMouse or no EGA/VGA found on your system.
; INTERNAL VARIABLES
OldHandler DD ? ; old mouse handler
OldEvents DW ? ; old event mask
Active DB 0 ; is our handler activated
MouseVisible DB 0 ; is mouse cursor visible
OldChars DB 4 DUP(?); saved characters under mask
OldPos DW ? ; where they were
CurX DW 0 ; current X coord
CurY DW 0 ; current Y coord
C1 DB 16 DUP(?); C1 character map
C3 DB 16 DUP(?); C3 character map
C2 DB 16 DUP(?); C2 character map
C4 DB 16 DUP(?); C4 character map
CharSize DW 16 ; character size (may be changed by CheckVideo)
XMin DW 0 ; mouse window x min limit
YMin DW 0 ; mouse window y min limit
XSize DW 639 ; mouse window x max limit
YSize DW 394 ; display height in pixels (VGA initialized)
YMax DW 394 ; mouse window y max limit
SaveBuffer DW 32 DUP(?); maps of internal characters saved here
C1C DW C1Code ; four characters used to substitute the mouse
C2C DW C2Code ; pointer - you should not use these codes
C3C DW C3Code ; elsewhere in your user interface.
C4C DW C4Code
ORMask: ; mask to be ORed with character maps
DW 00000000B
DB 01000000B
DB 01100000B
DB 01110000B
DB 01111000B
DB 01111100B
DB 01111110B
DB 01111111B
DB 01111100B
DB 01001100B
DB 00001110B
DB 00000110B
DB 00000110B
DB 00000000B
DB 00000000B
DB 00000000B
ANDMask: ; mask to be ANDed with character maps
DB 00111111B
DB 00011111B
DB 00001111B
DB 00000111B
DB 00000011B
DB 00000001B
DB 00000000B
DB 00000000B
DB 00000000B
DB 00000001B
DB 00100001B
DB 11110000B
DB 11110000B
DB 11110000B
DB 11111111B ; two lines will still unchanged for
DB 11111111B ; EGA 8x14 modes compatibility
; IMPLEMENTATION
gMouseHandler PROC FAR
test ax,1 ; we handle only movements
jz @@1
ifdef __use_286__
pusha
push es ds
else
push ax bx si di es ds
endif
mov al,cs:[MouseVisible] ; save mouse state on stack
push ax
call gHideMouse ; hide mouse if visible
call GetNewPos ; calculate new pointer position
pop ax
or al,al ; was pointer visible?
jz @@2 ; no, just update coordinates
call gShowMouse ; show mouse in new position
@@2:
ifdef __use_286__
pop ds es
popa
else
pop ds es di si bx ax
endif
@@1:
push ax
mov ax,cs:[CurY] ; convert Y coordinate to represent
cwd ; vertical position in universal pixels
div cs:[CharSize] ; that is this position divided by 8
ifdef __use_286__
shl ax,3
else
shl ax,1 ; will give character position -
shl ax,1 ; independent on character matrix size
shl ax,1
endif
mov cx,cs:[CurX] ; character matrix size by X is always
mov dx,ax ; 8, it need not be adjusted
and cl,0F8h
and dl,0F8h
pop ax
and ax,cs:[OldEvents] ; leave only events they want
jz @@Q ; are there any events left?
push ax ; check if OldHandler points somewhere
mov ax,_wp cs:[OldHandler]
or ax,_wp cs:[OldHandler][2]
pop ax
jz @@Q ; no handler defined
callf cs:[OldHandler] ; chain to old handler
@@Q:
jmp @@E
db 13,10,'g_Mouse Interface Version 1.42 Copyright (c) 1993,94 by B-coolWare.',13,10
@@E:
ret
ENDP
gInitMouse PROC FAR
; procedure gInitMouse; far;
; initializes mouse handler internal variables
ARG doModeFlip : BYTE
call checkVideo ; check if this is EGA/VGA and we're in
jc @@Q ; right mode
mov ax,3533h ; check interrupt vector
int 21h
mov ax,es
or bx,ax
jz @@Q
clr ax ; check if mouse support installed
int 33h
inc ax ; it will return 0FFFFh if installed,
jnz @@Q ; adding 1 will produce zero result
cmp doModeFlip,1
jnz @@noflip
call mode8bpc
@@noflip:
push cs:C1C
push cs:C2C
push cs:C3C
push cs:C4C
call LoadChars ; saving original character maps
push ds ; into SaveBuffer
push cs cs
pop ds es
lsi C1
ldi SaveBuffer
ifdef __use_386__
mov cx,16
cld
rep movsd
else
mov cx,32
cld
rep movsw
endif
pop ds
mov cs:[Active],1 ; we can operate
ldx gMouseHandler
mov cx,7Fh
mov ax,14h ; exchange event handlers
int 33h
mov _wp cs:[OldHandler],dx
mov _wp cs:[OldHandler][2],es
mov _wp cs:[OldEvents],cx
@@Q:
ret
ENDP
gShowMouse PROC FAR
; procedure gShowMouse; far;
; shows mouse pointer
cmp cs:[Active],0 ; are we operatable?
jz @@Q
cmp cs:[MouseVisible],1 ; is mouse already on screen?
jz @@Q
push ax si es ds
push cs
pop ds
call computeOffset ; compute offset in video buffer to
mov OldPos,si ; mouse pointer position
mov ax,0B800h
mov es,ax
mov al,es:[si] ; save characters currently there
mov OldChars,al
mov al,es:[si+2]
mov OldChars[1],al
mov al,es:[si+160]
mov OldChars[2],al
mov al,es:[si+162]
mov OldChars[3],al
push es si
call UpdateChars ; apply a mask on current chars
pop si es
mov al,_bp cs:[C1C]
mov ah,_bp cs:[C3C]
mov es:[si],al ; and put new chars on screen
mov es:[si+160],ah
cmp cs:[CurX],632 ; right bound?
jae @@10 ; yes - prevent wraparound
mov al,_bp cs:[C2C]
mov ah,_bp cs:[C4C]
mov _bp es:[si+2],al
mov _bp es:[si+162],ah
@@10:
pop ds es si ax
mov cs:[MouseVisible],1
@@Q:
ret
ENDP
gHideMouse PROC FAR
; procedure gHideMouse; far;
; hides mouse cursor
cmp cs:[Active],0
jz @@Q
cmp cs:[MouseVisible],0
jz @@Q
push ax ds es di cs
pop ds
mov di,OldPos
mov ax,0B800h
mov es,ax
mov al,OldChars ; put old characters back where
mov es:[di],al ; they were
mov al,OldChars[1]
mov es:[di+2],al
mov al,OldChars[2]
mov es:[di+160],al
mov al,OldChars[3]
mov es:[di+162],al
pop di es ds ax
mov cs:[MouseVisible],0
@@Q:
ret
ENDP
gMouseGotoXY PROC FAR
; procedure gMouseGotoXY(X,Y : Integer); far;
; sets new mouse position to (X,Y) (character position, not pixel)
ARG X,Y
cmp cs:[Active],1
jnz @@Q
ifdef __use_286__
pusha
push es ds
else
push ax bx cx dx si di es ds
endif
mov al,cs:[MouseVisible]
push ax
call gHideMouse ; hide mouse
mov ax,X ; compute pixel coordinates of
ifdef __use_286__
shl ax,3
else
shl ax,1 ; mouse pointer hotspot
shl ax,1
shl ax,1
endif
mov cs:[CurX],ax
mov ax,Y
mov cl,_bp cs:[CharSize]
mul cl
mov cs:[CurY],ax
pop ax
or al,al ; was mouse visible?
jz @@1
call gShowMouse ; yes - show it at new position
@@1:
ifdef __use_286__
pop ds es
popa
else
pop ds es di si dx cx bx ax
endif
@@Q:
ret
ENDP
gDoneMouse PROC FAR
; procedure gDoneMouse; far;
; resets mouse handler
ARG doModeFlip : BYTE
cmp cs:[Active],1
jnz @@Q
cmp doModeFlip,1
jnz @@noflip
call mode9bpc
@@noflip:
push ax cx si di ds es
call gHideMouse ; hide mouse pointer
push cs cs
pop ds es
lsi SaveBuffer ; restore character maps
ldi C1
ifdef __use_386__
mov cx,16
cld
rep movsd
else
mov cx,32
cld
rep movsw
endif
push cs:C1C
push cs:C2C
push cs:C3C
push cs:C4C
call SaveChars
mov ax,0Ch ; set event handler back to
mov cx,OldEvents ; original
mov es,_wp OldHandler
mov dx,_wp OldHandler[2]
int 33h
pop es ds di si cx ax
@@Q:
ret
ENDP
gMouseWhereX PROC FAR
; function gMouseWhereX : Integer; far;
mov ax,cs:[CurX] ; compute character position from pixel
ifdef __use_286__
shr ax,3
else
shr ax,1 ; position
shr ax,1
shr ax,1
endif
ret
ENDP
; function gMouseWhereY : Integer; far;
gMouseWhereY PROC FAR
push dx ; compute character position from pixel
mov ax,cs:[CurY] ; position
cwd
div cs:[CharSize]
pop dx
ret
ENDP
cgModeSet PROC NEAR
; program the video adapter so that we can get access to its character
; generator maps for reading/writing.
push ds si cx cs
pop ds
lsi MSData
mov cx,2
mov dx,3C4h
cld
cli
@@L:
lodsw
out dx,ax
jmp $+2
loop @@L
mov dl,0CEh
mov cl,3
@@L2:
lodsw
out dx,ax
jmp $+2
loop @@L2
pop cx si ds
ret
ENDP
MSData:
DW 0402h ; CPU writes to map 2
DW 0704h
DW 0005h
DW 0406h ; map starts at A000:0000 (64K)
DW 0204h ; CPU reads from map 2
cgModeClear PROC NEAR
; reset character generator to display mode.
push ds cx si cs
pop ds
lsi MCData
mov cx,2
cld
cli
mov dx,3C4h
@@L1:
lodsw
out dx,ax
jmp $+2
loop @@L1
sti
mov cl,3
mov dl,0CEh
@@L2:
lodsw
out dx,ax
jmp $+2
loop @@L2
pop si cx ds
ret
ENDP
MCData:
DW 0302h ; CPU writes to maps 0 and 1 (0011 mask)
DW 0304h ; odd-even addressing
DW 1005h ; enable odd-even addressing
DW 0E06h ; map starts at B800:0000
DW 0004h ; CPU reads from map 0
LoadChars PROC NEAR
ARG Code1,Code2,Code3,Code4
; load four character maps into C1,C2,C3 and C4
push ds es cs
pop es
mov cx,cs:[CharSize]
shr cx,1
mov ax,0A000h
mov ds,ax
cld
mov si,Code1
ldi C1
call LoadChar
mov si,Code2
ldi C2
call LoadChar
mov si,Code3
ldi C3
call LoadChar
mov si,Code4
ldi C4
call LoadChar
pop es ds
ret
ENDP
SaveChars PROC NEAR
ARG Code1,Code2,Code3,Code4
; copy C1,C2,C3 and C4 into video RAM
push ds es cs
pop ds
mov cx,cs:[CharSize]
shr cx,1
mov ax,0A000h
mov es,ax
cld
mov di,Code1
lsi C1
call SaveChar
mov di,Code2
lsi C2
call SaveChar
mov di,Code3
lsi C3
call SaveChar
mov di,Code4
lsi C4
call SaveChar
pop es ds
ret
ENDP
LoadChar PROC NEAR
; es:di -> buffer to fill
; bx = character code
push cx
ifdef __use_286__
shl si,5
else
mov cl,5
shl si,cl
endif
call MoveChar ; move CharSize bytes from ds:si -> es:di
pop cx
ret
ENDP
SaveChar PROC NEAR
; ds:si -> buffer to put into video RAM
; bx = character code
push cx
ifdef __use_286__
shl di,5
else
mov cl,5
shl di,cl
endif
call MoveChar
pop cx
ret
ENDP
MoveChar PROC NEAR
; ds:si -> source
; es:di -> dest
call cgModeSet ; set read/write mode from chargen'r
rep movsw
call cgModeClear ; reset normal operation mode
ret
ENDP
UpdateChars PROC NEAR
call computeOffset
mov ax,0B800h
mov es,ax
clr ah
mov al,es:[si] ; get original character maps...
push ax
mov al,es:[si+2]
push ax
mov al,es:[si+160]
push ax
mov al,es:[si+162]
push ax
call LoadChars
push cs ; ...apply masks on them...
pop ds
mov cx,CurX
mov bx,CurY
and cx,7
mov ax,CharSize
dec ax
and bx,ax
clr si
@@1:
cmp bx,CharSize
jz @@2
mov ah,_bp C1[bx]
mov al,_bp C2[bx]
mov dh,_bp ANDMask[si]
mov dl,0FFh
ror dx,cl
and ax,dx
mov dh,_bp ORMask[si]
clr dl
shr dx,cl
or ax,dx
mov _bp C1[bx],ah
mov _bp C2[bx],al
inc bx
inc si
cmp si,CharSize
jb @@1
jmp @@3
@@2:
clr bx
@@4:
mov ah,_bp C3[bx]
mov al,_bp C4[bx]
mov dh,_bp ANDMask[si]
mov dl,0FFh
ror dx,cl
and ax,dx
mov dh,_bp ORMask[si]
clr dl
shr dx,cl
or ax,dx
mov _bp C3[bx],ah
mov _bp C4[bx],al
inc bx
inc si
cmp si,CharSize
jb @@4
@@3:
push cs:C1C
push cs:C2C
push cs:C3C
push cs:C4C
call SaveChars
ret
ENDP
computeOffset PROC NEAR
; returns SI = offset in character buffer of character at (CurX,CurY)
push ax bx dx
mov si,cs:[CurX]
ifdef __use_286__
shr si,2
else
shr si,1
shr si,1
endif
mov ax,cs:[CurY]
cwd
mov bx,cs:[CharSize]
div bx
mov bl,160
mul bl
add si,ax
and si,0FFFEh ; we need character, not attibute
pop dx bx ax
ret
ENDP
GetNewPos PROC NEAR
mov ax,0Bh ; query last mouse motion
int 33h
add cs:[CurX],cx ; we don't convert mickeys to pixels, we
add cs:[CurY],dx ; just treat mickey counts as pixel counts
mov ax,cs:[CurX]
or ax,ax ; check screen boundaries
js @@6
cmp ax,cs:[XMin]
jae @@1
@@6:
clr ax
jmp @@2
@@1:
cmp ax,638
jb @@2
mov ax,638
@@2:
mov cs:[CurX],ax
mov ax,cs:[CurY]
or ax,ax
js @@5
cmp ax,cs:[YMin]
jae @@3
@@5:
clr ax
jmp @@4
@@3:
cmp ax,cs:[YSize]
jb @@4
mov ax,cs:[YSize]
@@4:
mov cs:[CurY],ax
ret
ENDP
isVGA proc
mov ax,1A00h
int 10h
cmp al,1Ah
ret
ENDP
checkVideo PROC NEAR
call isVGA
jz @@Ok ; VGA
push es
mov ax,40h
mov es,ax
mov al,es:[87h]
pop es
or al,al
jz @@Fail ; not EGA
mov cs:[CharSize],14
mov cs:[YSize],344 ; ScreenHeightPix - 1
mov cs:[YMax],344
@@Ok:
mov ah,0Fh
int 10h
cmp al,3 ; 80x25 text mode?
jnz @@Fail ; we won't operate in any other mode
clc
ret
@@Fail:
stc
ret
ENDP
i33h:
push ax
mov ah,0Fh
int 10h
cmp al,3 ; video mode 3?
pop ax
jnz @@JOld ; we do not operating in any other modes
cmp cs:[Active],0
jz @@JOld ; we're not active
cmp ax,1 ; show mouse pointer
jz @@1
cmp ax,2 ; hide mouse pointer
jz @@2
cmp ax,3 ; get mouse position and button count
jz @@3
cmp ax,4 ; move mouse pointer
jz @@4
cmp ax,7 ; set horizontal range
jz @@7
cmp ax,8 ; set vertical range
jz @@8
cmp ax,0Ch ; set new handler
jz @@0C
cmp ax,14h ; exchange handlers
jz @@14
@@JOld:
db 0EAh ; jump to previous handler
Save33 dd 0
@@1: ; show mouse
call gShowMouse
iret
@@2: ; hide mouse
call gHideMouse
iret
@@3: ; get mouse position and button count
pushf
callf cs:[Save33]
push ax ; replace CX,DX with our virtual
mov ax,cs:[CurY] ; coordinates
cwd
div cs:[CharSize]
ifdef __use_286__
shl ax,3
else
shl ax,1
shl ax,1
shl ax,1
endif
mov cx,cs:[CurX]
mov dx,ax
and cl,0F8h
and dl,0F8h
pop ax
iret
@@4: ; move pointer
mov cs:[CurX],cx
push dx
ifdef __use_286__
shr dx,3
else
shr dx,1
shr dx,1
shr dx,1
endif
push ax
mov ax,dx
mul _bp cs:[CharSize]
mov cs:[CurY],ax
pop ax
pop dx
iret
@@7: ; set horizontal range
mov cs:[XMin],cx
mov cs:[XSize],dx
iret
@@8: ; set vertical range
push ax
mov ax,cx
ifdef __use_286__
shr ax,3
else
shr ax,1
shr ax,1
shr ax,1
endif
mul _bp cs:[CharSize]
mov cs:[YMin],ax
mov ax,dx
ifdef __use_286__
shr ax,3
else
shr ax,1
shr ax,1
shr ax,1
endif
mul _bp cs:[CharSize]
cmp ax,cs:[YMax]
jae @@81
mov cs:[YSize],ax
@@81:
pop ax
iret
@@0C: ; set new handler
mov _wp cs:[OldEvents],cx
mov _wp cs:[OldHandler],dx
mov _wp cs:[OldHandler][2],es
iret
@@14: ; exchange handlers
push ax
xchg cx,cs:[OldEvents]
xchg _wp cs:[OldHandler],dx
mov ax,es
xchg _wp cs:[OldHandler][2],ax
mov es,ax
pop ax
iret
Intercept33 PROC FAR
cmp cs:[Active],1
jnz @@Q
push ds
clr ax
mov ds,ax
mov si,33h*4
push cs
pop es
ldi Save33
cld
ifdef __use_386__
movsd
else
movsw
movsw
endif
push ds
pop es
mov di,33h*4
load ax,i33h
cli
stosw
mov ax,cs
stosw
sti
pop ds
@@Q:
ret
ENDP
Untercept33 PROC FAR
mov ax,_wp cs:[Save33]
or ax,_wp cs:[Save33][2]
jz @@Q
push ds
clr ax
mov es,ax
mov di,33h*4
push cs
pop ds
lsi Save33
cld
cli
ifdef __use_386__
movsd
else
movsw
movsw
sti
pop ds
endif
@@Q:
ret
ENDP
mode8bpc PROC NEAR
; sets 8x16 character matrix mode on VGAs
call isVGA
jnz @@noflip
cli
mov dx,3C4h ; sequencer
mov al,1
out dx,al ; clocking mode 3c5(1)
inc dx
in al,dx ; clocking value
or al,1 ; set 8 dots/char
out dx,al ; write value
mov dx,3CCh ; miscellaneous register ( read )
in al,dx
and al,0F3h ; 14 MHz ( 8 dots )
mov dx,3C2h ; miscellaneous register ( write )
out dx,al
mov dx,3DAh ; force address mode
in al,dx
mov dx,3C0h ; Attribute controller
mov al,13h ; horizontal pixel panning
out dx,al
clr al ; shift data left = 0
out dx,al
mov al,20h ; set bit 5 to 1 ( enable display )
out dx,al
sti
mov _bp cs:[C1C],1
mov _bp cs:[C2C],2
mov _bp cs:[C3C],3
mov _bp cs:[C4C],4
@@noflip:
ret
ENDP
mode9bpc PROC NEAR
; sets 9x16 character matrix mode on VGAs
call isVGA
jnz @@noflip
cli
mov dx,3C4h ; sequencer
mov al,1
out dx,al ; clocking mode 3c5(1)
inc dx
in al,dx ; clocking value
and al,0FEh ; set 9 dots/char
out dx,al ; write value
mov dx,3CCh ; miscellaneous register ( read )
in al,dx
and al,0F3h
or al,4 ; 16 Mhz ( 9 dots )
mov dx,3C2h ; miscellaneous register ( write )
out dx,al
mov dx,3DAh ; force address mode
in al,dx
mov dx,3C0h ; Attribute controller
mov al,13h ; horizontal pixel panning
out dx,al
clr al ; shift data left = -1
dec al
out dx,al
mov al,20h ; set bit 5 to 1 ( enable display )
out dx,al
sti
@@noflip:
ret
ENDP
gMouseActive PROC FAR
; returns Boolean flag indicating that gMouse event handler is currently active
mov al,cs:[Active]
ret
ENDP
gMouseSetChars PROC FAR
; procedure gMouseSetChars( C1, C2, C3, C4 : Char ); far;
ARG Code1 : BYTE, Code2 : BYTE, Code3 : BYTE, Code4 : BYTE
mov al,Code1
mov cs:C1C,ax
mov al,Code2
mov cs:C2C,ax
mov al,Code3
mov cs:C2C,ax
mov al,Code4
mov cs:C4C,ax
ret
ENDP
gMouseGetChars PROC FAR
; procedure gMouseGetChars( var C1, C2, C3, C4 : Char ); far;
ARG Code1 : DWORD, Code2 : DWORD, Code3 : DWORD, Code4 : DWORD
mov ax,cs:C1C
les di,Code1
stosb
mov ax,cs:C2C
les di,Code2
stosb
mov ax,cs:C3C
les di,Code3
stosb
mov ax,cs:C4C
les di,Code4
stosb
ret
ENDP
; that's all, folks!
END